/**
 * @file Logger.cpp
 * @author  haifeng (haifengxiao@icloud.com)
 * @brief
 * @version 0.1
 * @date 2021-07-06
 *
 * @copyright Copyright (c) 2021
 *
 */

#include "Logger.h"
#include "FileLogAppender.h"
#include "StdoutLogAppender.h"
#include "../../Config/inc/Config.h"

namespace Chen {
    namespace Log {

        Logger::Logger(const std::string& name)
            : m_name(name), m_level(LogLevel::DEBUG_) {
            m_formatter.reset(new LogFormatter("%d{%Y-%m-%d %H:%M:%S}%T%t%T%N%T%F%T[%p]%T[%c]%T%f:%l%T%m%n"));
        }

        void Logger::log(LogLevel::Level level, LogEvent::ptr event) {
            //如果日志级别大于日志器的级别
            if (level >= m_level) {
                auto self = shared_from_this();
                //向该日志器的所有输出地输出日志
                if (!m_appenders.empty()) {
                    for (auto& item : m_appenders) {
                        item->log(self, level, event);
                    }
                }
                //如果输出地为空 那么则输出到主logger 主logger 缺省输出到控制台？
                else if (m_root) {
                    m_root->log(level, event);
                }
            }
        }

        void Logger::debug(LogEvent::ptr event) {
            log(LogLevel::DEBUG_, event);
        }

        void Logger::info(LogEvent::ptr event) {
            log(LogLevel::INFO, event);
        }

        void Logger::warn(LogEvent::ptr event) {
            log(LogLevel::WARN, event);
        }

        void Logger::error(LogEvent::ptr event) {
            log(LogLevel::ERROR, event);
        }

        void Logger::fatal(LogEvent::ptr event) {
            log(LogLevel::FATAL, event);
        }

        void Logger::addAppender(std::shared_ptr<LogAppender> appender) {
            m_appenders.push_back(appender);
        }

        void Logger::delAppender(std::shared_ptr<LogAppender> appender) {
            for (auto it = m_appenders.begin();
                it != m_appenders.end();it++)     {
                if (*it == appender) {
                    m_appenders.erase(it);
                    break;
                }
            }
        }

        void Logger::clearAppenders() {
            m_appenders.clear();
        }

        LogFormatter::ptr Logger::getFormatter() {
            return m_formatter;
        }

        void Logger::setFormatter(const std::string& val) {
            std::cout << "-------" << val << std::endl;
            LogFormatter::ptr new_val(new LogFormatter(val));
            if (new_val->isError()) {
                std::cout << "Logger setFormatter name=" << m_name
                    << " value=" << val << " invalid formatter"
                    << std::endl;
                return;
            }
            setFormatter(new_val);
        }

        void Logger::setFormatter(LogFormatter::ptr val) {
            m_formatter = val;
            for (auto item : m_appenders) {
                if (!item->m_hasFormatter) {
                    item->m_formatter = m_formatter;
                }
            }
        }

        struct LogAppenderDefine {
            int type = 0;
            LogLevel::Level level = LogLevel::Level::UNKNOW;
            std::string formatter;
            std::string file;

            bool operator == (const LogAppenderDefine& oth) const {
                return type == oth.type
                    && level == oth.level
                    && formatter == oth.formatter
                    && file == oth.file;
            }
        };

        struct LogDefine {
            std::string name;
            LogLevel::Level level = LogLevel::Level::UNKNOW;
            std::string formatter;
            std::vector<LogAppenderDefine> appenders;

            bool operator == (const LogDefine& oth) const {
                return name == oth.name
                    && level == oth.level
                    && formatter == oth.formatter
                    && appenders == oth.appenders;
            }

            bool operator < (const LogDefine& oth) const {
                return name < oth.name;
            }

            bool isvaild() const {
                return !name.empty();
            }
        };

        // Chen::Conf::ConfigVal<std::set<LogDefine>>::ptr g_log_defines = 
        //     Chen::Conf::Config::Lookup("logs",std::set<LogDefine>(),"logs config");

        // struct LogIniter{
        //     LogIniter(){
        //         g_log_defines->addListenser(0xF1E231,[](const std::set<LogDefine>& old_value,
        //                     const std::set<LogDefine>& new_value)
        //         {
        //             for(auto& i : new_value){
        //                 auto it = old_value.find(i);
        //                 Chen::Log::Logger::ptr logger;
        //                 if(it == old_value.end()){
        //                     //新增logger
        //                     logger = CHEN_LOG_NAME(i.name);
        //                 }
        //                 else
        //                 {
        //                     if(!(i == *it)){
        //                         logger = CHEN_LOG_NAME(i.name);
        //                     }
        //                 }

        //                 logger->setLevel(i.level);
        //                 if(!i.formatter.empty()){
        //                     logger->setFormatter(i.formatter);             
        //                 }

        //                 logger->clearAppenders();
        //                 for(auto& a : i.appenders){
        //                     Chen::Log::LogAppender::ptr ap;
        //                     if(a.type == 1){
        //                         ap.reset(new FileLogAppender(a.file));
        //                     }
        //                     else if(a.type == 2){
        //                         ap.reset(new StdoutLogAppender);
        //                     }
        //                     ap->setLevel(a.level);
        //                     logger->addAppender(ap);
        //                 }
        //             }

        //             for(auto& i : old_value){
        //                 auto it = new_value.find(i);
        //                 if(it == new_value.end()){
        //                     //删除
        //                     auto logger = CHEN_LOG_NAME(i.name);
        //                     logger->setLevel((LogLevel::Level)100);
        //                     logger->clearAppenders();
        //                 }
        //             }

        //         });
        //     }
        // };

        // 静态对象在main函数之前就已经被创建了
        //static LogIniter __log_init;

    }//namespace Log
}//namespace Chen
